/* 
 * File: Texture
 * Created: 15-JUN-2011
 * Author: Colin Gall-McDaid
 * 
 * Description: Texture helper class. Loads a bitmap from an asset and creates and 
 * binds a texture object from it. Also provides a method to dispose of the it when
 * done.
 */
package com.gallsoft.games.framework.gl;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

import com.gallsoft.games.framework.FileIO;
import com.gallsoft.games.framework.impl.GLGame;
import com.gallsoft.games.framework.impl.GLGraphics;


public class Texture {

    private GLGraphics glGraphics;
    private FileIO fileIO;
    private String fileName;
    private int textureId;
    private int minFilter;
    private int magFilter;
    
    public int width;
    public int height;
    
    /**
     * Constructor.
     * 
     * @param glGame
     *          OpenGL game object
     * @param fileName
     *          texture filename
     */
    public Texture(GLGame glGame, String fileName) {
        this.glGraphics = glGame.getGLGraphics();
        this.fileIO = glGame.getFileIO();
        this.fileName = fileName;
        
        load();
    }
    
    /**
     * Load a texture into OpenGL.
     */
    private void load() {
        GL10 gl = glGraphics.getGL();
        int[] textureIds = new int[1];
        gl.glGenTextures(1, textureIds, 0);
        textureId = textureIds[0];
        
        InputStream in = null;
        
        try {
            in = fileIO.readAsset(fileName);
            Bitmap bitmap = BitmapFactory.decodeStream(in);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
            setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
            
            width = bitmap.getWidth();
            height = bitmap.getHeight();
            
            bitmap.recycle();
        } catch (IOException e) {
            throw new RuntimeException("Couldn't load texture '" + fileName + "'", e);
        } finally {
            if (in != null)
                try { in.close(); } catch (IOException e) {}
        }
    }
    
    /**
     * Reload a texture after OpenGL context is lost.
     */
    public void reload() {
        load();
        bind();
        setFilters(minFilter, magFilter);
        glGraphics.getGL().glBindTexture(GL10.GL_TEXTURE_2D, 0);
    }
    
    /**
     * Set the texture filter options.
     * 
     * @param minFilter
     *              minification option
     * @param magFilter
     *              magnification option
     */
    public void setFilters(int minFilter, int magFilter) {
        this.minFilter = minFilter;
        this.magFilter = magFilter;
        
        GL10 gl = glGraphics.getGL();
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, minFilter);
    }
    
    /**
     * Bind the texture.
     */
    public void bind() {
        GL10 gl = glGraphics.getGL();
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
    }
    
    /**
     * Dispose of texture.
     */
    public void dispose() {
        GL10 gl = glGraphics.getGL();
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
        int[] textureIds = { textureId };
        gl.glDeleteTextures(1, textureIds, 0);
    }
}
